package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzyl.constant.CacheConstant;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.service.impl.handler.FirstFilterHandler;
import com.zzyl.service.impl.handler.SecondFilterHandler;
import com.zzyl.service.impl.handler.ThirdFilterHandler;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.UserThreadLocal;
import com.zzyl.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;


    /**
     * 根据条件查询菜单列表
     *
     * @param resourceDto
     * @return
     */
    @Override
    @Cacheable(cacheNames = CacheConstant.RESOURCE_LIST,key = "#resourceDto.hashCode()")
    public List<ResourceVo> list(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        List<Resource> list = resourceMapper.list(resource);
        return BeanUtil.copyToList(list, ResourceVo.class);
    }

    /**
     * 构建树形结构
     *
     * @param resourceDto
     * @return
     */
    @Override
    @Cacheable(cacheNames = CacheConstant.RESOURCE_TREE, key = "#resourceDto.hashCode()")
    public TreeVo resourceTreeVo(ResourceDto resourceDto) {
        //1. 创建返回数据的对象
        TreeVo treeVo = new TreeVo();

        //2. 创建根节点 并构建目录关系
        TreeItemVo root = new TreeItemVo();
        root.setId(SuperConstant.ROOT_PARENT_ID);
        root.setLabel("智慧养老院");

        List<TreeItemVo> list = new ArrayList<>();
        list.add(root);
        treeVo.setItems(list);

        //3. 通过条件查询所有的菜单节点
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        resource.setParentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID));
        resource.setDataState(SuperConstant.DATA_STATE_0);
        resource.setResourceType(SuperConstant.MENU);
        List<Resource> listResource = resourceMapper.list(resource);

        FirstFilterHandler firstFilterHandler = new FirstFilterHandler();
        SecondFilterHandler secondFilterHandler = new SecondFilterHandler();
        ThirdFilterHandler thirdFilterHandler = new ThirdFilterHandler();

        //构建关系
        firstFilterHandler.setNextHanlder(secondFilterHandler);
        secondFilterHandler.setNextHanlder(thirdFilterHandler);

        firstFilterHandler.filter(listResource, root);

        //4. 通过节点查找所有的一级目录 并构建关系
        /*List<Resource> firstTree = new ArrayList<>();
        for (Resource r : listResource) {
            if(r.getParentResourceNo().equals(root.getId())){
                firstTree.add(r);
            }
        }*/
       /* List<Resource> firstTree = listResource.stream().filter(r -> {
            if (r.getParentResourceNo().equals(root.getId())) {
                return true;
            } else {
                return false;
            }
        }).collect(Collectors.toList());

        List<TreeItemVo> firstTreeList = firstTree.stream().map(r -> {
            TreeItemVo vo = new TreeItemVo();
            vo.setId(r.getResourceNo());
            vo.setLabel(r.getResourceName());
            return vo;
        }).collect(Collectors.toList());

        //构建关系
        root.setChildren(firstTreeList);
        //5. 遍历每一个一级目录 然后找找对应的一级目录下的二级目录 并构建关系
        root.getChildren().stream().map(first -> {
            List<Resource> secondTree = listResource.stream().filter(r -> {
                if (r.getParentResourceNo().equals(first.getId())) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());

            List<TreeItemVo> secondTreeList = secondTree.stream().map(r -> {
                TreeItemVo vo = new TreeItemVo();
                vo.setId(r.getResourceNo());
                vo.setLabel(r.getResourceName());
                return vo;
            }).collect(Collectors.toList());

            first.setChildren(secondTreeList);

            return first;
        }).collect(Collectors.toList());

        //6. 遍历每一个二级目录 然后找找对应的二级目录下的三级目录 并构建关系
        root.getChildren().stream().map(first -> {
            first.getChildren().stream().map(second -> {
                List<Resource> thirdTree = listResource.stream().filter(r -> {
                    if (r.getParentResourceNo().equals(second.getId())) {
                        return true;
                    } else {
                        return false;
                    }
                }).collect(Collectors.toList());

                List<TreeItemVo> thirdTreeList = thirdTree.stream().map(r -> {
                    TreeItemVo vo = new TreeItemVo();
                    vo.setId(r.getResourceNo());
                    vo.setLabel(r.getResourceName());
                    return vo;
                }).collect(Collectors.toList());

                second.setChildren(thirdTreeList);

                return second;
            }).collect(Collectors.toList());

            return first;
        }).collect(Collectors.toList());*/

        //7. 返回结果

        return treeVo;
    }

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = CacheConstant.RESOURCE_TREE, allEntries = true),
            @CacheEvict(cacheNames = CacheConstant.RESOURCE_LIST, allEntries = true)
    })
    public void createResource(ResourceDto resourceDto) {
        //1. 把dto转换为pojo
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);

        //2. 根据夫资源的no查询父菜单 然后把当前菜单的状态设置为父菜单的状态
        Resource r = new Resource();
        r.setParentResourceNo(resource.getParentResourceNo());
        Resource parent = resourceMapper.selectByParentNo(resource.getParentResourceNo());
        if(parent == null){
            throw new BaseException(BasicEnum.PARENT_MENU_NOT_EXIST);
        }
        resource.setDataState(parent.getDataState());

        //3. 补齐常规字段
        resource.setCreateTime(LocalDateTime.now());
        resource.setUpdateTime(LocalDateTime.now());
        resource.setCreateBy(1671403256519078006L);
        resource.setLabel(resource.getRequestPath().replaceAll("/",":"));
        resource.setRemark(resource.getResourceName());

        //4. 根据父资源的编码生成子资源的编码
        resource.setResourceNo(createResourceNo(resource.getParentResourceNo(), resource.getResourceType()));

        //5. 新增菜单
        resourceMapper.insert(resource);
    }

    /**
     * 生成子菜单的no
     * @param parentResourceNo
     * @param resourceType
     * @return
     */
    private String createResourceNo(String parentResourceNo, String resourceType) {
        if(null != resourceType && resourceType.equals(SuperConstant.MENU))
        {
            //100001 012 001 000
            if(NoProcessing.processString(parentResourceNo).length() > 12){
                throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
            }
        }

        // 通过父菜单的no查询所有的子菜单 如果没有子菜单 则直接追加001 如果有子菜单 则找到最大的那个no 然后在+1
        Resource resource = new Resource();
        resource.setParentResourceNo(parentResourceNo);
        List<Resource> subMenu = resourceMapper.list(resource);
        if(null == subMenu || subMenu.size() == 0){
            //如果没有子菜单 则直接追加001
            return NoProcessing.createNo(parentResourceNo, false);
        }else{
            // 如果有子菜单 则找到最大的那个no 然后在+1
            Long maxNo = subMenu.stream().map(r -> Long.parseLong(r.getResourceNo())).max(Comparator.comparing(i -> i)).get();
            return NoProcessing.createNo(maxNo + "", true);
        }

    }

    /**
     * 通过用户查询权限菜单
     *
     * @return
     */
    @Override
    public List<MenuVo> menu() {
        //1. 根据ThreadLocal查询当前登录的用户
        Long userId = UserThreadLocal.get();

        //2. 通过用户id查询用户的所有的菜单
        List<MenuVo> menuVoList = resourceMapper.selectMenuByUserId(userId);

        //3. 根据菜单的父no进行分组统计
        Map<String, List<MenuVo>> parentMap = menuVoList.stream().collect(Collectors.groupingBy(MenuVo::getParentResourceNo));

        //4. 遍历每一个菜单 用自己的resourceno到统计结果中查询数据 如果有子菜单 则设置关系
        menuVoList.forEach(menuVo -> {
            //构建redirect 和meta
            menuVo.setRedirect("/" + menuVo.getName());
            MenuMetaVo menuMetaVo = new MenuMetaVo();
            menuMetaVo.setTitle(menuVo.getName());
            menuVo.setMeta(menuMetaVo);

            List<MenuVo> subList = parentMap.get(menuVo.getResourceNo());
            if(!EmptyUtil.isNullOrEmpty(subList)){
                menuVo.setChildren(subList);
            }
        });

        //5. 获取根菜单的所有子菜单并返回
        return parentMap.get(SuperConstant.ROOT_PARENT_ID);
    }
}
